﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Win32;
using System.Windows;
using System.Xml;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Controls;
using System.IO;
using SHomeWorkshop.LunarMind.Converts;

namespace SHomeWorkshop.LunarMind.Commands
{
    /// <summary>
    /// 以此类为模板，制作自定义命令类
    ///     共需要修改１０处！！！
    /// ==============================
    /// 
    /// 导出为图像文件命令。
    /// ★①，修改类名。
    /// </summary>
    public static class OutportToSplitedImageFileCommand
    {
        private static RoutedUICommand routedUICmd;//创建私有字段

        public static RoutedUICommand RoutedUICmd//创建只读静态属性
        {
            get { return routedUICmd; }
        }

        /// <summary>
        /// ★②，修改静态构造方法名。
        /// </summary>
        static OutportToSplitedImageFileCommand()//类型构造器
        {
            //★③，修改两个字符串参数名。★④以及第三个参数的类型名。
            routedUICmd = new RoutedUICommand(
                "OutportToSplitedImageFileCommand",
                "OutportToSplitedImageFileCommand",
                typeof(OutportToSplitedImageFileCommand),//创建RoutedUICommand对象
                null//不需要快捷键
                );

            cmdBinding.Command = routedUICmd;
            cmdBinding.CanExecute += new CanExecuteRoutedEventHandler(cmdBinding_CanExecute);
            cmdBinding.Executed += new ExecutedRoutedEventHandler(cmdBinding_Executed);
        }

        private static CommandBinding cmdBinding = new CommandBinding();

        public static CommandBinding CmdBinding
        {
            get { return cmdBinding; }
        }

        static void cmdBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //★⑦，修改此方法的实现。

            OutportToSplitedImageFile();
        }

        internal static bool OutportToSplitedImageFile(string fileFullPath = null)
        {
            double scale = ScaleValueConverter.GetNewScaleValue(Globals.MainWindow.sliderOfCanvasScale.Value);

            if (scale < 1)
            {
                MessageBoxResult r = MessageBox.Show("　　当前文档的缩放比例小于１，导出的图片文件可能比较模糊。要继续吗？",
                    Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Warning);
                if (r != MessageBoxResult.Yes) return false;
            }

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = Globals.AppName + "——导出图片：";
            sfd.Filter = "标记图像格式(*.tiff)|*.tiff";

            sfd.FileName = Globals.MainWindow.GetDefaultFileName();//无路径。

            string defFileFullPath = "";
            string defFileNamePrefix = sfd.FileName;

            int indexOfDot = defFileNamePrefix.LastIndexOf('.');
            if (indexOfDot > -1)
            {
                defFileNamePrefix = defFileNamePrefix.Substring(0, indexOfDot);
            }

            sfd.FileName = defFileNamePrefix + "_" + "文档图切片";
            sfd.InitialDirectory = defFileFullPath;

            bool? result = sfd.ShowDialog();

            if (result != true) return false;

            string filename;

            if (sfd.FileName.EndsWith(".tiff"))
            {
                filename = sfd.FileName.Substring(0, sfd.FileName.Length - 5);
            }
            else { filename = sfd.FileName; }
            //这个对话框应先弹出来，否则会令用户无所适从。

            System.Windows.Media.Imaging.RenderTargetBitmap rtb;
            //BitmapEncoder encoder;

            //bool isPng = filename.EndsWith(".png");
            //if (isPng)
            //{

            //    rtb = OutportToImageFileCommand.GetExpressionImage(false); ;//96DPI
            //    encoder = new PngBitmapEncoder();
            //}
            //else
            //{
            rtb = OutportToImageFileCommand.GetExpressionImage();//300DPI//切片主要就是为打印，因此，不需要支持其它格式。
            //encoder = new TiffBitmapEncoder();
            //}

            if (rtb == null)
            {
                MessageBox.Show("发生意外错误，未能获取当前文档的图形，无法继续打印！",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            // PixelFormats.Pbgra32

            Rect wholeRect = new Rect(0, 0, rtb.PixelWidth, rtb.PixelHeight);

            PaperInfo curPaperInfo = Globals.MainWindow.PageSetting;

            int width, height;
            if (Globals.MainWindow.PageDirection == Orientation.Horizontal)
            {
                width = curPaperInfo.LongSidePixcelCount;
                height = curPaperInfo.ShortSidePixcelCount;
            }
            else
            {
                height = curPaperInfo.LongSidePixcelCount;
                width = curPaperInfo.ShortSidePixcelCount;
            }

            //取出页面宽、高
            int paperWidth = width;
            int paperHeight = height;

            Thickness margin = new Thickness(20);//暂时不支持页边距功能，固定每页留空白边。

            //Wpf是96DPI，而我要打印的图像是300DPI。3.25是比例值。
            width = (int)(width - margin.Left * 3.25 - margin.Right * 3.25);
            height = (int)(height - margin.Top * 3.25 - margin.Bottom * 3.25);

            int offcetX = 0, offcetY = 0;

            bool endX = false;
            bool endY = false;
            try
            {
                List<BitmapSource> bitmapSources = new List<BitmapSource>();

                do
                {
                    int realHeight;

                    if (offcetY + height > wholeRect.Height)
                    {
                        realHeight = (int)wholeRect.Height - offcetY;
                        endY = true;
                    }
                    else
                    {
                        realHeight = height;
                    }

                    do
                    {
                        int realWidth;

                        if (offcetX + width > wholeRect.Width)
                        {
                            realWidth = (int)wholeRect.Width - offcetX;
                            endX = true;
                        }
                        else
                        {
                            realWidth = width;
                        }

                        Int32Rect pieceRect;

                        if (width <= 0 || height <= 0) break;

                        pieceRect = new Int32Rect(offcetX, offcetY, realWidth, realHeight);
                        var array = new byte[realWidth * realHeight * rtb.Format.BitsPerPixel / 8];//每像素需要32位（4字节）。

                        rtb.CopyPixels(pieceRect, array, realWidth * rtb.Format.BitsPerPixel / 8, 0);

                        //跨度，每行像素数据的总字节数
                        //int stride = rtb.PixelWidth * rtb.Format.BitsPerPixel / 8;
                        //stride += 4 - stride % 4; //补上几个字节，使其可以被4整除 

                        BitmapSource newBitmapSource = BitmapImage.Create(realWidth, realHeight, 300, 300,
                            PixelFormats.Pbgra32, null, array, realWidth * rtb.Format.BitsPerPixel / 8);

                        bitmapSources.Add(newBitmapSource);

                        offcetX += width;

                    } while (offcetX <= wholeRect.Width && endX == false);

                    offcetY += height;
                    offcetX = 0; endX = false;
                } while (offcetY <= wholeRect.Height && endY == false);

                //向磁盘循环写出所有图片文件。            
                for (int i = 1; i <= bitmapSources.Count; i++)
                {
                    BitmapSource bitmapSource = bitmapSources[i - 1];
                    TiffBitmapEncoder encoder = new TiffBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
                    using (Stream stm = File.Create(filename + "_" + i.ToString("D4") + ".tiff"))
                    {
                        encoder.Save(stm);
                    }
                }

                GC.Collect();

                MessageBox.Show("图像切片已全部导出。", Globals.AppName,
                    MessageBoxButton.OK, MessageBoxImage.Information);
                return true;
            }
            catch (Exception ex)
            {
                Dialogs.LunarMsgBox.MsgBoxShow(
                        Globals.AppName,
                        "未能顺利导出全部图像切片。",
                        "异常信息如下：\r\n" + ex.Message,
                        ex.StackTrace);
                return false;
            }
        }

        static void cmdBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //★⑧，修改此方法的实现。
            e.CanExecute = true;//总是可以导出图片的。
        }
    }
}
